<template>
	<view class="drag-list" :style="warpStyle" :list="dataList" :baseData="baseData" :change:list="handler.listObserver"
		:change:baseData="handler.baseDataObserver">
		<view class="drag-item" :style="`width: ${ 100 / columns }%; height: ${itemHeight}rpx`"
			v-for="(item, index) in dataList" :key="item.id" :data-index="index" @longpress="handler.longPress"
			@touchmove="handler.touchMove" @touchend="handler.touchEnd">

			<slot :data="item.data"></slot>
		</view>
		<view class="mark"></view>
	</view> 
</template>

<script module="handler" src="./index.wxs" lang="wxs"></script>
<script setup lang="ts">
	import { ref, reactive, toRefs, getCurrentInstance, onMounted, nextTick, watch } from "vue";

	const emits = defineEmits(["sortChange"]); 
	const props = defineProps({
		list: {
			type: Array,
			default: () => [],
		},
		columns: {
			type: Number,
			default: 1,
		},
		itemHeight: {
			type: Number,
			default: 0,
		},
	})
	const { list, columns, itemHeight } = toRefs(props);

	let dataList = ref([]), // 添加排序信息后的数据
		rows = ref(0), // 行数-计算获得 
		warpStyle = ref(""), // 容器样式-计算获得 
		key = 0;
	const baseData : any = reactive({}); // 基础信息
	const currentInstance = getCurrentInstance();

	// 获取列表容器相对屏幕的位置信息及item的宽高信息（TIP: 获取一次即可）
	const getSystemInfoAndDomInfo = () => {
		// 设备信息
		const {
			windowWidth,
			windowHeight,
			platform
		} = uni.getSystemInfoSync();
		baseData.windowWidth = windowWidth;
		baseData.windowHeight = windowHeight;
		baseData.platform = platform;
		// DOM信息
		const query = uni.createSelectorQuery().in(currentInstance.proxy);
		query.select(".drag-item").boundingClientRect();
		query.select(".drag-list").boundingClientRect();
		query.exec(([itemRes, wrapRes]) => {
			baseData.itemWidth = itemRes.width;
			baseData.itemHeight = itemRes.height;
			baseData.wrapLeft = wrapRes.left;
			baseData.wrapTop = wrapRes.top;
		})
	};

	// 更新列表数据、行列信息及容器的高度
	const updateDataList = (list : any) => { 
		key = 0;
		dataList.value = list.map((item : any, index) => {
			item.data = { ...item };
			const oldSortMeta = item?.sortMeta || {}
			const realKey = oldSortMeta?.realKey === undefined ? key++ : oldSortMeta.realKey;
			const sortKey = oldSortMeta?.sortKey === undefined ? index : oldSortMeta.sortKey; // 整体顺序
			const tranX = oldSortMeta?.tranX === undefined ? `${(sortKey % columns.value) * 100}%` : oldSortMeta.tranX;
			const tranY = oldSortMeta?.tranY === undefined ? `${Math.floor(sortKey / columns.value) * 100}%` : oldSortMeta.tranY; 
			item.sortMeta = {
				realKey,
				sortKey,
				tranX,
				tranY,
			}
			return item;
		});
		rows.value = Math.ceil(list.length / columns.value);
		baseData.rows = rows.value;
		baseData.columns = columns.value;
		warpStyle.value = `height: ${rows.value * itemHeight.value}rpx`
		console.log('%c [ updateDataList ]: ', 'color: #ffffff; background: pink; font-size: 13px;', dataList.value)
	}

	const init = () => {
		updateDataList(list.value);
		setTimeout(() => {
			getSystemInfoAndDomInfo();
		}, 0)
	};
	onMounted(() => {
		init();
	})

	let isScroll = ref(false),
		timer = null;
	const androidPageScroll = (data : any) => {
		if (isScroll.value) return
		isScroll.value = true;
		timer = setTimeout(() => {
			uni.pageScrollTo({
				scrollTop: data.scrollTop,
				duration: 0
			});
			clearTimeout(timer)
			timer = null
			isScroll.value = false;
		}, 10)
	}
	const iosPageScroll = (data : any) => {
		uni.pageScrollTo({
			scrollTop: data.scrollTop,
			duration: 300
		})
	}
	let handlePageSroll = (data : any) => {
		if (baseData.platform === "android") {
			handlePageSroll = androidPageScroll;
		} else {
			handlePageSroll = iosPageScroll;
		}
		handlePageSroll(data);
	}

	let vibrate = (data) => {
		console.log('%c [ vibrate ]: ', 'color: #bf2c9f; background: pink; font-size: 13px;', data)
		if (baseData.platform !== "devtools") {
			vibrate = function () {
				uni.vibrateShort();
			}
		} else {
			vibrate = function () { }
		}
		vibrate();
	}

	const sortEnd = (data : any) => {
		console.log('%c [ sortEnd111 ]: ', 'color: #ffffff; background: pink; font-size: 13px;', data)
		// emits("sortChange", data.list) 
		emits("sortChange", data.realListData)
	}

	watch(() => list.value, (newVal) => {
		console.log('%c [ list ]: ', 'color: #ffffff; background: pink; font-size: 13px;', newVal)
		updateDataList(newVal);
	})

	defineExpose({
		handlePageSroll,
		vibrate,
		sortEnd,
	})
</script>
<style scoped lang="scss">
	.drag-list {
		width: 750rpx;
		position: relative;
		overflow: hidden;

		.drag-item {
			position: absolute;
			z-index: 1;
			top: 0;
			left: 0;

			view {
				width: 100%;
				height: 100%;
			}

			&.tran {
				transition: transform 0.3s !important;
			}

			&.cur {
				z-index: 3;
			}

			&.fixed {
				z-index: 0 !important;
			}
		}

		.mark {
			display: none;
			position: fixed;
			width: 100vh;
			height: 100vh;
			z-index: 2;
			background-color: transparent;
		}
	}
</style>